#include "Game_view.h"

Game_view::Game_view()
{
    string error;

    mgw = new Game_window;
    if(mgw == NULL || !mgw->create_game_window(800,600,32,false, "Lines - a tetris clone"))
    {
        error = "Something went wrong initializing the window. What did you do!?";
        throw error;
    }

    mp_game_table=NULL;
    current_piece=NULL;
    next_piece = NULL;

    //initialize game state
    gamestate = GS_INITIALIZING;

    //get window height
    float y = mgw->getHeight();

    bh = y - 10*y/50; //Board height
    bw = bh/GRID_HEIGHT*GRID_WIDTH;//x/4; //Board width

    // Create a pixmap font from a TrueType file.
    font = new FTGLPixmapFont("fonts/TawattypeII1.ttf");

    // If something went wrong, bail out.
    if(font->Error())
    {
        error = "Something went wrong initializing the text font/s. Perhaps you have deleted the fonts folder... Aborting program!";
        throw error;
    }

    //Initialize audio system
    if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096)<0)
    {
        error = "Something went wrong initializing the audio system... Aborting program!";
        throw error;
    }

    Mix_AllocateChannels(2);

    n_lines = 0;
    score = 0;
    level = 1;
}

Game_view::~Game_view()
{
    Mix_CloseAudio();
    SAFE_DELETE(mgw);
    SAFE_DELETE(font);
}


/****************************************************** RENDERING METHOD ****************************************************/

void Game_view::Render()
{

    //Get window width and height
    float x = mgw->getWidth();
    float y = mgw->getHeight();

    //Rendering
    switch(gamestate)
    {
        case GS_INITIALIZING:
        {
            //Initialize window
            resize(mgw->getWidth(), mgw->getHeight());

            sounds[0] = Mix_LoadWAV("sounds/button-9.wav");
            if(sounds[0] == NULL)
            {
                cerr << "Error loading sound" << endl;
            }
            Mix_VolumeChunk(sounds[0], 100);

            sounds[1] = Mix_LoadWAV("sounds/bottle_pop_2.wav");
            if(sounds[1] == NULL)
            {
                cerr << "Error loading sound" << endl;
            }
            Mix_VolumeChunk(sounds[1], 100);


            //Initialize OpenGL screen options
            glShadeModel(GL_SMOOTH);                // Enable Smooth Shading
            glEnable(GL_LINE_SMOOTH);
            glClearColor(112.0/255.0, 164.0/255.0, 251.0/255.0, 1.0f);   // Grey Background
            glClear(GL_COLOR_BUFFER_BIT);
            glLoadIdentity();

            gamestate = GS_RUNNING;

            break;
        }
        case GS_RUNNING:
        {
            glClear(GL_COLOR_BUFFER_BIT);
            glLoadIdentity();

            //Translate all to start drawing from the bottom left of the table
            glTranslatef(x/6, y/50*5, 0);


            Background_render();

            Draw_pieces();
            Grid_render();
            //Patch_render();//Render a very ugly patch
            Text_render();


            break;
        }
        case GS_GAMEOVER:
        {
            glClear(GL_COLOR_BUFFER_BIT);
            glLoadIdentity();

            //Translate all to start drawing from the bottom left of the table
            glTranslatef(x/6, y/50*5, 0);

            Background_render();
            Draw_pieces();
            Grid_render();
            Patch_render();//Render a very ugly patch
            Text_render();

            break;
        }

        //State used when we have to wait for the Game View
        case GS_WAIT:
        {

        }

        //default case
        default:
        {
            cout << gamestate << endl;
            string error = "Game_View:Strange gamestate. Something weird happened...";
            throw error;
        break;
        }
    }

    SDL_GL_SwapBuffers();
}

void Game_view::Patch_render()
{

    //Draw board inside
    glColor3f(112.0/255.0, 164.0/255.0, 251.0/255.0);

    glBegin(GL_TRIANGLES);

    glVertex2f(-2, bh+2);
    glVertex2f(bw+2, bh+2);
    glVertex2f(-2, mgw->getHeight());

    glEnd();

    glBegin(GL_TRIANGLES);

    glVertex2f(bw+2, bh+2);
    glVertex2f(bw+2, mgw->getHeight());
    glVertex2f(-2, mgw->getHeight());

    glEnd();

    //Draw board outline
    glColor3f(1.0f,0.0f,0.0f);

    glBegin(GL_LINE_LOOP);

    glVertex2f(-2, -2);
    glVertex2f(bw+2, -2);
    glVertex2f(bw+2, bh+2);
    glVertex2f(-2, bh+2);

    glEnd();

}

//Renders game's environment
bool Game_view::Background_render()
{
    //get window width
    float x = mgw->getWidth();

    //Draw board inside
    glColor3f(217.0/255.0,247.0/255.0,194.0/255.0);

    glBegin(GL_TRIANGLES);

    glVertex2f(-2, -2);
    glVertex2f(bw+2, -2);
    glVertex2f(-2, bh+2);

    glEnd();

    glBegin(GL_TRIANGLES);

    glVertex2f(bw+2, -2);
    glVertex2f(bw+2, bh+2);
    glVertex2f(-2, bh+2);

    glEnd();

    //Draw board outline
    glColor3f(1.0f,0.0f,0.0f);

    glBegin(GL_LINE_LOOP);

    glVertex2f(-2, -2);
    glVertex2f(bw+2, -2);
    glVertex2f(bw+2, bh+2);
    glVertex2f(-2, bh+2);

    glEnd();

    //Draw next block box
    float boxw = bw/GRID_WIDTH*5.5;
    float boxh = bh/GRID_HEIGHT*6;
    float box_pos[2] = {bw+x/10, bh-boxh};

    glTranslatef(box_pos[0],box_pos[1],0);

    glColor3f(1.0f, 1.0f, 1.0f);

    glBegin(GL_TRIANGLES);

    glVertex2f(0, 0);
    glVertex2f(boxw, 0);
    glVertex2f(0, boxh);

    glEnd();

    glBegin(GL_TRIANGLES);

    glVertex2f(boxw, 0);
    glVertex2f(boxw, boxh);
    glVertex2f(0, boxh);

    glEnd();

    //Draw box outline
    glColor3f(1.0f,0.0f,0.0f);

    glBegin(GL_LINE_LOOP);

    glVertex2f(0, 0);
    glVertex2f(boxw, 0);
    glVertex2f(boxw, boxh);
    glVertex2f(0, boxh);

    glEnd();

    glTranslatef(-box_pos[0],-box_pos[1],0);

    return true;
}

void Game_view::Draw_pieces()
{
    int size = current_piece->getSize();
    float x = mgw->getWidth();
    float sq_w = bw/GRID_WIDTH;
    float sq_h = bh/GRID_HEIGHT;
    int cp_row = current_piece->getPosition(0)*sq_h;
    int cp_col = current_piece->getPosition(1)*sq_w;
    int rp_col = bw+x/10 + bw/GRID_WIDTH*1.5;
    int rp_row = bh - 2*bh/GRID_HEIGHT;


    for(float i=0; i<size; i++)
    {
       for(float j=0; j<size; j++)
       {
           //draw square for current piece
           if(current_piece->getMatPos(i,j))
            Draw_square(cp_col+j*sq_w, cp_row-i*sq_h, current_piece->getColor());

           //draw square for next piece
           if(next_piece->getMatPos(i,j))
            Draw_square(rp_col+j*sq_w, rp_row-i*sq_h, next_piece->getColor());
       }
    }

    //
}

void Game_view::Draw_square(float posx, float posy, int color)
{
    float sq_w = bw/GRID_WIDTH;
    float sq_h = bh/GRID_HEIGHT;

    glTranslatef(posx, posy ,0);

    switch(color)
    {
        case piece::C_BLUE:
            glColor3f(0.0f, 0.0f, 1.0f);
        break;

        case piece::C_GREEN:
            glColor3f(0.0f, 1.0f, 0.0f);
        break;

        case piece::C_RED:
            glColor3f(1.0f, 0.0f, 0.0f);
        break;

        case piece::C_YELLOW:
            glColor3f(1.0f, 1.0f, 0.0f);
        break;

        case piece::C_PURPLE:
            glColor3f(1.0f, 0.0f, 1.0f);
        break;

        case piece::C_ORANGE:
            glColor3f(0.95f, 0.4f, 0.0f);
        break;

        case piece::C_WHITE:
            glColor3f(1.0f, 1.0f, 1.0f);
        break;

        //default is RED
        default:
            glColor3f(1.0f, 1.0f, 0.0f);
        break;
    }


    glBegin(GL_TRIANGLES);

    glVertex2f(0, 0);
    glVertex2f(sq_w, 0);
    glVertex2f(0, sq_h);

    glEnd();

    glBegin(GL_TRIANGLES);

    glVertex2f(sq_w, 0);
    glVertex2f(sq_w, sq_h);
    glVertex2f(0, sq_h);

    glEnd();

    //Draw box outline
    glColor3f(0.0f,0.0f,0.0f);

    glBegin(GL_LINE_LOOP);

    glVertex2f(0, 0);
    glVertex2f(sq_w, 0);
    glVertex2f(sq_w, sq_h);
    glVertex2f(0, sq_h);

    glEnd();

    glTranslatef(-posx, -posy ,0);
}


//Renders the content of the grid
bool Game_view::Grid_render()
{

    for(float i=0; i<GRID_HEIGHT; i++)
    {
        for( float j=0; j<GRID_WIDTH; j++)
        {
            if((mp_game_table->Get_board_pos(i,j))->full)
                Draw_square(j*bw/GRID_WIDTH, i*bh/GRID_HEIGHT, (mp_game_table->Get_board_pos(i,j))->color);
        }
    }
    return true;
}

void Game_view::resize(int x, int y)
{
    std::cout << "Resizing Window to " << x << "x" << y << std::endl;

    if (y <= 0)
    {
        y = 1;
    }

    glViewport(0,0,x,y);

//glViewport(0,0,x,y);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glOrtho(0, x, 0, y, 0, 0);

    gluOrtho2D(0, x, 0, y);
    glDisable(GL_DEPTH_TEST);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void Game_view::Text_render()
{

    //get window width and height
    float x = mgw->getWidth();
    float y = mgw->getHeight();

    //buffer used to transform int to string
    char buffer [24];

    // Set the font size .
    font->FaceSize(24);

    glPixelTransferf(GL_RED_BIAS, -0.0f);
    glPixelTransferf(GL_GREEN_BIAS, -1.0f);
    glPixelTransferf(GL_BLUE_BIAS, -1.0f);

    //Render text
    font->Render("SCORE",-1,FTPoint(bw+x/10+x/6, y/10*5.5));
    font->Render("LINES",-1,FTPoint(bw+x/10+x/6, y/10*4.0));
    font->Render("LEVEL",-1,FTPoint(bw+x/10+x/6, y/10*2.5));

    glPixelTransferf(GL_RED_BIAS, -1.0f);
    glPixelTransferf(GL_GREEN_BIAS, -1.0f);
    glPixelTransferf(GL_BLUE_BIAS, -1.0f);


    //render score
    snprintf(buffer, 24, "%d", score);
    font->Render(buffer,-1,FTPoint(bw+x/10+x/6, y/10*5));

    //render number of lines
    snprintf(buffer, 24, "%d", n_lines);
    font->Render(buffer,-1,FTPoint(bw+x/10+x/6, y/10*3.5));

    //render level
    snprintf(buffer, 24, "%d", level);
    font->Render(buffer,-1,FTPoint(bw+x/10+x/6, y/10*2));


    if(gamestate == GS_GAMEOVER)
    {

        float rw = x/2;
        float rh = y/2;

        glTranslatef(x/10, y/5, 0);

        //Draw board inside
        glColor3f(0.0f,0.0f,0.0f);

        glBegin(GL_TRIANGLES);

        glVertex2f(0, 0);
        glVertex2f(rw, 0);
        glVertex2f(0, rh);

        glEnd();

        glBegin(GL_TRIANGLES);

        glVertex2f(rw, 0);
        glVertex2f(rw, rh);
        glVertex2f(0, rh);

        glEnd();

        glTranslatef(+x/16, -y/4, 0);

        //set font size
        font->FaceSize(50);

        glPixelTransferf(GL_RED_BIAS, -0.0f);
        glPixelTransferf(GL_GREEN_BIAS, -0.0f);
        glPixelTransferf(GL_BLUE_BIAS, -1.0f);

        //Render text
        font->Render("GAME OVER",-1,FTPoint(x*0.33, y/1.8));

        font->FaceSize(16);
        font->Render("(PRESS 'SPACE' TO RESTART)",-1,FTPoint(x*0.35, y/2.2));

    }

}

void Game_view::Restart_game()
{
    //Restart game variables
    n_lines = 0;
    score = 0;
    level = 1;

    gamestate = GS_RUNNING;

}


